package com.digitalchina.dcn.dcss.web.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import com.digitalchina.dcn.dcss.portal.server.PortalServer;
import com.digitalchina.dcn.dcss.portal.util.PortalContext;
import com.digitalchina.dcn.dcss.web.service.UserService;
import com.digitalchina.dcn.dcss.web.service.RoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import com.digitalchina.dcn.dcss.web.model.User;
import com.digitalchina.dcn.dcss.web.security.PermissionSign;
import com.digitalchina.dcn.dcss.web.security.RoleSign;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 * 用户控制器
 * 
 * @author StarZou
 * @since 2014年5月28日 下午3:54:00
 **/
@Controller
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PortalServer portalServer;


    /**
     * 登录页
     */
    @RequestMapping("/login")
    public String login() {
        return "login";
    }

    /**
     * 用户登录
     * 
     * @param user
     * @param result
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@Valid User user, boolean rememberMe, BindingResult result, Model model, HttpServletRequest request) {
        try {
            Subject subject = SecurityUtils.getSubject();
            // 已登陆则 跳到首页
            if (subject.isAuthenticated()) {
                return "redirect:/";
            }
            if (result.hasErrors()) {
                model.addAttribute("error", "参数错误！");
                return "login";
            }
            // 身份验证
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
            token.setRememberMe(rememberMe);
            subject.login(token);
            // 验证成功在Session中保存用户信息
            // 已通过SysUserFilter 过滤器在Session中保存用户信息
//            final User authUserInfo = userService.selectByUsername(user.getUsername());
//            request.getSession().setAttribute("userInfo", authUserInfo);

//            portalServer.startUserAuth(acip, request.getRemoteAddr(), user.getUsername(), user.getPassword());

        } catch (AuthenticationException e) {
            // 身份验证失败
            model.addAttribute("error", "用户名或密码错误 ！");
            return "login";
        }
        return "redirect:/";
    }

    /**
     * 用户登出
     * 
     * @param session
     * @return
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(HttpSession session, HttpServletRequest request) {
        session.removeAttribute("userInfo");
        // 登出操作
        Subject subject = SecurityUtils.getSubject();
        subject.logout();

//        portalServer.startUserLogout(request.getRemoteAddr());

        return "login";
    }

    /**
     * 登录页
     */
    @RequestMapping("/auth")
    public String startAuth() {
        return "portal-login";
    }

    @RequestMapping(value = "/auth", method = RequestMethod.POST)
    public DeferredResult<ModelAndView> startAuth(String wlanacip, @Valid User user, HttpServletRequest request) {
        final DeferredResult<ModelAndView> authResult = new DeferredResult<>(PortalContext.HTTP_TIMEOUT);

        portalServer.startUserAuthAsyncCall(authResult, wlanacip,
                request.getRemoteAddr(), user.getUsername(), user.getPassword());
        // 超时直接返回登录界面
        authResult.onTimeout(new Runnable() {
            @Override
            public void run() {
                ModelAndView model = new ModelAndView("portal-login");
                authResult.setResult(model);
            }
        });

        return authResult;
    }

    @RequestMapping(value = "/auth/logout")
    public DeferredResult<ModelAndView> startLogout(HttpServletRequest request, String wlanacip) {
        final DeferredResult<ModelAndView> authResult = new DeferredResult<>(PortalContext.HTTP_TIMEOUT);

        portalServer.startUserLogoutAsyncCall(authResult, wlanacip, request.getRemoteAddr());
        // 超时提示
        authResult.onTimeout(new Runnable() {
            @Override
            public void run() {
                ModelAndView model = new ModelAndView("portal-result");
                model.addObject("titile", "下线失败");
                model.addObject("result", "下线失败");
                authResult.setResult(model);
            }
        });

        return authResult;
    }

    /**
     * 基于角色 标识的权限控制案例
     */
    @RequestMapping(value = "/admin")
    @ResponseBody
    @RequiresRoles(value = RoleSign.ADMIN)
    public String admin() {
        return "拥有admin角色,能访问";
    }

    /**
     * 基于权限标识的权限控制案例
     */
    @RequestMapping(value = "/create")
    @ResponseBody
    @RequiresPermissions(value = PermissionSign.USER_CREATE)
    public String create() {
        return "拥有user:create权限,能访问";
    }

    @RequestMapping(method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("userList", userService.findAll());
        return "user/list";
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String showCreateForm(Model model) {
        setCommonData(model);
        model.addAttribute("user", new User());
        model.addAttribute("op", "新增");
        return "user/edit";
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public String create(User user, RedirectAttributes redirectAttributes) {
        userService.createUser(user);
        redirectAttributes.addFlashAttribute("msg", "新增成功");
        return "redirect:/rest/user";
    }

    @RequestMapping(value = "/{id}/update", method = RequestMethod.GET)
    public String showUpdateForm(@PathVariable("id") Long id, Model model) {
        setCommonData(model);
        model.addAttribute("user", userService.findOne(id));
        model.addAttribute("op", "修改");
        return "user/edit";
    }

    @RequestMapping(value = "/{id}/update", method = RequestMethod.POST)
    public String update(User user, RedirectAttributes redirectAttributes) {
        userService.updateUser(user);
        redirectAttributes.addFlashAttribute("msg", "修改成功");
        return "redirect:/rest/user";
    }

    @RequestMapping(value = "/{id}/delete", method = RequestMethod.GET)
    public String showDeleteForm(@PathVariable("id") Long id, Model model) {
        setCommonData(model);
        model.addAttribute("user", userService.findOne(id));
        model.addAttribute("op", "删除");
        return "user/edit";
    }

    @RequestMapping(value = "/{id}/delete", method = RequestMethod.POST)
    public String delete(@PathVariable("id") Long id, RedirectAttributes redirectAttributes) {
        userService.deleteUser(id);
        redirectAttributes.addFlashAttribute("msg", "删除成功");
        return "redirect:/rest/user";
    }

    @RequestMapping(value = "/{id}/changePassword", method = RequestMethod.GET)
    public String showChangePasswordForm(@PathVariable("id") Long id, Model model) {
        model.addAttribute("user", userService.findOne(id));
        model.addAttribute("op", "修改密码");
        return "user/changePassword";
    }

    @RequestMapping(value = "/{id}/changePassword", method = RequestMethod.POST)
    public String changePassword(@PathVariable("id") Long id, String newPassword, RedirectAttributes redirectAttributes) {
        userService.changePassword(id, newPassword);
        redirectAttributes.addFlashAttribute("msg", "修改密码成功");
        return "redirect:/rest/user";
    }

    private void setCommonData(Model model) {
        model.addAttribute("roleList", roleService.findAll());
    }
}
